<?xml version="1.0" encoding="UTF-8"?><d:tdl xmlns="http://www.w3.org/1999/xhtml" xmlns:b="http://www.backbase.com/2006/btl"  xmlns:d="http://www.backbase.com/2006/tdl" >

	<d:namespace name="http://www.backbase.com/2006/btl">

		<d:uses element="positionElement dimensionElement" src="../visualElement/visualElement.xml"/>
		<d:uses element="disableElement" src="../disableElement/disableElement.xml"/>
		<d:uses element="dataObserver" src="../dataBinding/dataBinding.xml"/>
		<d:uses element="dataTemplate" src="../dataTemplate/dataTemplate.xml"/>

		<d:document>
			<d:handler event="mousedown" type="text/javascript"><![CDATA[
				// when not clicking on a menu, close active menu
				var oActiveDataMenu = btl.dataMenu.activeDataMenu;
				if (oActiveDataMenu && oActiveDataMenu != event.target) {
					oActiveDataMenu.setProperty('open', false);
					btl.dataSource.actionRequest(oActiveDataMenu, 'update');
				}
			]]></d:handler>
		</d:document>

		<d:element name="dataMenuCommonBase" extends="b:dataTemplate b:positionElement b:dimensionElement" abstract="true">
			

			

			<d:resource type="text/javascript"><![CDATA[
				if (!btl.dataMenu)
					btl.dataMenu = {};

				btl.dataMenu.activeDataMenu = null;

				/**
				 * Builds instance node for a record and returns it
				 * @param oDocument The document to create the node for
				 * @param oDataSource Reference to the datasource
				 * @param sItem The record ID of the item
				 */
				btl.dataMenu.buildInstanceItem = function(oDocument, oDataSource, sItem, sBaseUri) {
					var oItem = oDocument.createElement('item');

					oItem.setAttribute('id', sItem);
					var sSeparator = btl.dataSource.getValue(oDataSource, sItem, 'separator');
					if (sSeparator) {
						oItem.setAttribute('separator', sSeparator);
						return oItem;	// no need to build the rest
					}
					var sName = btl.dataSource.getValue(oDataSource, sItem, 'name');
					if (sName.length !== null) {
						var oName = oDocument.createElement('name');
						oName.appendChild(oDocument.createTextNode(sName));
						oItem.appendChild(oName);
					}
					var sIcon = btl.dataSource.getValue(oDataSource, sItem, 'icon');
					if (sIcon !== null) {
						var oIcon = oDocument.createElement('icon');
						oIcon.appendChild(oDocument.createTextNode(bb.uri.resolveUri(sIcon, sBaseUri)));
						oItem.appendChild(oIcon);
					}
					var sHasSubmenu = btl.dataSource.getValue(oDataSource, sItem, 'hasSubmenu');
					if (sHasSubmenu == 'true') {
						oItem.setAttribute('hasSubmenu', sHasSubmenu);
					}
					var sOpen = btl.dataSource.getValue(oDataSource, sItem, 'open');
					if (sOpen) {
						oItem.setAttribute('open', sOpen);
					}
					// recur if node is open
					if (sOpen == 'true') {
						var aItems = btl.dataSource.getLinked(oDataSource, sItem, 'submenu');
						var oSubmenu = oDocument.createElement('submenu');
						for (var i=0, len = aItems.length; i < len; i++) {
							var oSubmenuItem = btl.dataMenu.buildInstanceItem(oDocument, oDataSource, aItems[i], sBaseUri);
							oSubmenu.appendChild(oSubmenuItem);
						}
						oItem.appendChild(oSubmenu);
					}
					return oItem;
				};
			]]></d:resource>

			<d:method name="buildInstanceItem">
				<d:argument name="document"/>
				<d:argument name="dataSource"/>
				<d:argument name="recordID"/>
				<d:body type="text/javascript"><![CDATA[
					return btl.dataMenu.buildInstanceItem(document, dataSource, recordID,
						this.getProperty('baseURI'));
				]]></d:body>
			</d:method>

			<d:method name="getOpen">
				
				<d:argument name="identifier">
					
				</d:argument>
				<d:body type="text/javascript"><![CDATA[
					var oDataSource = this.getProperty('dataSource');
					return btl.dataSource.getValue(oDataSource, identifier, 'open') == 'true';
				]]></d:body>
			</d:method>

			<d:method name="setOpen">
				
				<d:argument name="identifier">
					
				</d:argument>
				<d:argument name="value">
					
				</d:argument>
				<d:body type="text/javascript"><![CDATA[
					var oDataSource = this.getProperty('dataSource');
					var oNode = this.getInstanceNode(identifier);
					var sLastOpenId = this.getProperty('lastOpenId');

					// if previously opened is not an ancestor: close previously opened
					if (value) {
						if (sLastOpenId && sLastOpenId != identifier) {
							var oLoopNode = oNode;
							while (oLoopNode && oLoopNode.nodeType == 1 && oLoopNode.getAttribute('id') != sLastOpenId) {
								oLoopNode = oLoopNode.parentNode;
							}
							if (!oLoopNode || oLoopNode.nodeType != 1) {
								var oLoopNode = this.getInstanceNode(sLastOpenId);
								while (oLoopNode.nodeType == 1) {
									var oLoopNode2 = oNode;
									while (oLoopNode2 && oLoopNode2.nodeType == 1 && oLoopNode2 != oLoopNode) {
										oLoopNode2 = oLoopNode2.parentNode;
									}
									if (oLoopNode2 && oLoopNode2.nodeType == 1)
										break;
									var sId = oLoopNode.getAttribute('id');
									if (sId && btl.dataSource.getValue(oDataSource, sId, 'open') == 'true')
										btl.dataSource.setValue(oDataSource, sId, 'open', 'false');
									oLoopNode = oLoopNode.parentNode;
								}
							}
						}
					} else {
						var oLoopNode = oNode;
						while (oLoopNode && oLoopNode.nodeType == 1) {
							var sId = oLoopNode.getAttribute('id');
							if (sId && btl.dataSource.getValue(oDataSource, sId, 'open') == 'true')
								btl.dataSource.setValue(oDataSource, sId, 'open', 'false');
							oLoopNode = oLoopNode.parentNode;
						}
					}

					// set open value
					btl.dataSource.setValue(oDataSource, identifier, 'open', value ? 'true' : 'false');

					this.setProperty('lastOpenId', value ? identifier : null);
				]]></d:body>
			</d:method>

			<d:method name="hasSubmenu">
				
				<d:argument name="identifier">
					
				</d:argument>
				<d:body type="text/javascript"><![CDATA[
					var oDataSource = this.getProperty('dataSource');
					return btl.dataSource.getValue(oDataSource, identifier, 'hasSubmenu') == 'true';
				]]></d:body>
			</d:method>

			<d:method name="isSeparator">
				
				<d:argument name="identifier">
					
				</d:argument>
				<d:body type="text/javascript"><![CDATA[
					var oDataSource = this.getProperty('dataSource');
					return btl.dataSource.getValue(oDataSource, identifier, 'separator') == 'true';
				]]></d:body>
			</d:method>

			<d:method name="getParentId">
				
				<d:argument name="identifier">
					
				</d:argument>
				<d:body type="text/javascript"><![CDATA[
					var oNode = this.getInstanceNode(identifier)
					var oParent = oNode.parentNode.parentNode;
					if (oParent && oParent.nodeType == 1)
						return oParent.getAttribute('id') || null;
				]]></d:body>
			</d:method>

			<d:method name="isSubMenuItem">
				
				<d:argument name="identifier">
					
				</d:argument>
				<d:body type="text/javascript"><![CDATA[
					var oNode = this.getInstanceNode(identifier);
					if (oNode)
						return oNode.parentNode.nodeName == 'submenu';
					else
						return false;
				]]></d:body>
			</d:method>

			<d:attribute name="openDelay" default="300">
				
			</d:attribute>

			<d:property name="openDelay">
				<d:getter type="text/javascript"><![CDATA[
					var iOpenDelay = parseInt(this.hasAttribute('openDelay'));
					return isNaN(iOpenDelay) ? 300 : iOpenDelay;
				]]></d:getter>
			</d:property>

			<d:property name="currentHoverId">
				
			</d:property>

			<d:property name="lastOpenId">
				
			</d:property>

			<d:property name="open">
				
				<d:setter type="text/javascript"><![CDATA[
					this._._open = value;
					if (value) {
						if (btl.dataMenu.activeDataMenu && btl.dataMenu.activeDataMenu != this)
							btl.dataMenu.activeDataMenu.setProperty('open', false);
						btl.dataMenu.activeDataMenu = this;
					} else {
						if (btl.dataMenu.activeDataMenu == this)
							btl.dataMenu.activeDataMenu = null;
						var sLastOpen = this.getProperty('lastOpenId');
						if (sLastOpen) {
							this.setOpen(sLastOpen, false);
						}
					}
					// call method for view stuff
					this.setMenuOpen(value);
				]]></d:setter>
			</d:property>

			<d:property name="mouseDownId">
				
			</d:property>

			<d:handler event="mouseenter" match="[btl_data-id]" type="text/javascript"><![CDATA[
				var oTarget = event.currentView;
				var sId = this.getIdFromView(oTarget);
				this.setProperty('currentHoverId', sId);

				if (!this.getProperty('open'))
					return;

				// expand after 300ms
				var iOpenDelay = oTarget.tagName.toLowerCase() == 'td' ? 0 : this.getProperty('openDelay');
				var oController = this;
				fOpener = function() {
						if (oController.getProperty('currentHoverId') == sId) {
							if (oController.hasSubmenu(sId)) {
								if (!oController.getOpen(sId)) {
									oController.setOpen(sId, true);
									btl.dataSource.actionRequest(oController, 'update');
								}
							} else {
								var sLastOpenId = oController.getProperty('lastOpenId');
								if (sLastOpenId) {
									var sParentId = oController.getParentId(sId);
									if (sParentId && sLastOpenId != sParentId) {
										oController.setOpen(sParentId, true);
										btl.dataSource.actionRequest(oController, 'update');
									}
									if (!sParentId) {
										oController.setOpen(sLastOpenId, false);
										btl.dataSource.actionRequest(oController, 'update');
									}
								}
							}
						}
					};
				if (iOpenDelay)
					setTimeout(fOpener, iOpenDelay);
				else
					fOpener();
			]]></d:handler>

			<d:handler event="mouseleave" match="[btl_data-id]" type="text/javascript"><![CDATA[
				var oTarget = event.currentView;
				var sId = this.getIdFromView(oTarget);
				if (this.getProperty('currentHoverId') == sId)
					this.setProperty('currentHoverId', null);
			]]></d:handler>

			<d:handler event="mousedown" type="text/javascript"><![CDATA[
				var sId = this.getIdFromView(event.viewTarget);
				this.setProperty('mouseDownId', sId);
				if (sId && this.hasSubmenu(sId)) {
					// if clicked on item with submenu
					if (!this.isSubMenuItem(sId)) {
						// if clicked on item in menu bar
						var bOpen = !this.getProperty('open');
						this.setProperty('open', bOpen);
						if (bOpen && !this.getOpen(sId))
							this.setOpen(sId, true);
						btl.dataSource.actionRequest(this, 'update');
					} else {
						// if clicked on item in submenu with sub-submenu
						this.setOpen(sId, true);
						btl.dataSource.actionRequest(this, 'update');
					}
				}
			]]></d:handler>

			<d:handler event="mouseup" type="text/javascript"><![CDATA[
				var sId = this.getIdFromView(event.viewTarget);
				if (sId && !this.hasSubmenu(sId) && !this.isSeparator(sId) && sId == this.getProperty('mouseDownId')) {
					var event = bb.document.createEvent('CustomEvent');
					event.initCustomEventNS(null, 'menuActivate', true, false, sId);
					this.dispatchEvent(event);
					this.setProperty('open', false);
					btl.dataSource.actionRequest(this, 'update');
				}
			]]></d:handler>

			<d:destructor type="text/javascript"><![CDATA[
				if (btl.dataMenu.activeDataMenu == this)
					btl.dataMenu.activeDataMenu = null;
			]]></d:destructor>
		</d:element>

		<d:element name="dataMenuBase" abstract="true">
			

			<d:property name="instance">
				
				<d:getter type="text/javascript"><![CDATA[
					if (!this._._instance)
						this._._instance = bb.xml.parse('<?xml version="1.0" encoding="UTF-8"?><menu/>').documentElement;
					return this._._instance;
				]]></d:getter>
			</d:property>
		</d:element>

		<d:element name="dataContextMenuBase" abstract="true">
			

			<d:resource type="text/javascript"><![CDATA[
				if (!btl.dataMenu)
					btl.dataMenu = {};

				btl.dataMenu.handleContextMenu = function btl_menu_handleContextMenu(eEvent) {
					if (eEvent.currentTarget.__contextMenu && !eEvent.defaultPrevented) {
						var oContextMenu = eEvent.currentTarget.__contextMenu;

						if (oContextMenu) {
							var mode = 'at-pointer',
								top = bb.viewport.scrollTop + eEvent.clientY,
								left = bb.viewport.scrollLeft + eEvent.clientX;
							bb.html.position(oContextMenu.viewNode, null, mode, left, top);
							oContextMenu.setProperty('open', true);
							eEvent.stopPropagation();
							eEvent.preventDefault();
						}
					}
				};
			]]></d:resource>

			<d:property name="instance">
				
				<d:getter type="text/javascript"><![CDATA[
					if (!this._._instance)
						this._._instance = bb.xml.parse('<?xml version="1.0" encoding="UTF-8"?><submenu/>').documentElement;
					return this._._instance;
				]]></d:getter>
			</d:property>

			<d:handler event="DOMNodeRemovedFromDocument" type="text/javascript"><![CDATA[
				var oParent = this.getProperty('parentNode');
				oParent.removeEventListener('contextmenu', btl.dataMenu.handleContextMenu, false);
				oParent.__contextMenu = null;
			]]></d:handler>

			<d:handler event="DOMNodeInsertedIntoDocument" type="text/javascript"><![CDATA[
				var oParent = this.getProperty('parentNode');
				oParent.__contextMenu = this;
				oParent.addEventListener('contextmenu', btl.dataMenu.handleContextMenu, false);
			]]></d:handler>
		</d:element>
	</d:namespace>
</d:tdl>